package com.jeesite.modules.interceptor;

import com.jeesite.modules.utils.JwtUtils;
import com.jeesite.modules.utils.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * Token刷新拦截器
 * 第一个拦截器，负责检查Token有效期并自动刷新
 */
@Component
@Order(1)
public class TokenRefreshInterceptor implements HandlerInterceptor {
    
    private static final Logger logger = LoggerFactory.getLogger(TokenRefreshInterceptor.class);
    
    @Autowired
    private JwtUtils jwtUtils;
    
    @Autowired
    private RedisUtils redisUtils;
    
    // 不需要刷新Token的路径
    private static final List<String> EXCLUDE_PATHS = Arrays.asList(
        "/api/auth/login",
        "/api/auth/register",
        "/api/auth/server-status",
        "/error",
        "/favicon.ico"
    );
    
    // Token刷新阈值：15分钟（毫秒）
    private static final long REFRESH_THRESHOLD = 15 * 60 * 1000;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        String contextPath = request.getContextPath();
        
        // 移除上下文路径
        if (StringUtils.hasText(contextPath)) {
            requestURI = requestURI.substring(contextPath.length());
        }
        
        // 检查是否是排除路径
        if (isExcludePath(requestURI)) {
            return true;
        }
        
        // OPTIONS请求直接放行
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }
        
        try {
            // 获取Token
            String token = getTokenFromRequest(request);
            if (!StringUtils.hasText(token)) {
                return true; // 没有Token，交给下一个拦截器处理
            }
            
            // 验证Token基本有效性
            if (!jwtUtils.validateToken(token)) {
                return true; // Token无效，交给下一个拦截器处理
            }
            
            // 检查Token是否需要刷新
            Date expirationDate = jwtUtils.getExpirationDateFromToken(token);
            long currentTime = System.currentTimeMillis();
            long timeUntilExpiration = expirationDate.getTime() - currentTime;
            
            // 如果Token在15分钟内过期，生成新Token
            if (timeUntilExpiration <= REFRESH_THRESHOLD && timeUntilExpiration > 0) {
                String username = jwtUtils.getUsernameFromToken(token);
                Long userId = jwtUtils.getUserIdFromToken(token);
                
                // 生成新Token
                String newToken = jwtUtils.generateToken(username, userId);
                
                // 更新Redis中的Token
                redisUtils.setToken(username, newToken, 86400); // 24小时
                
                // 在响应头中返回新Token
                response.setHeader("new-access-token", newToken);
                
                logger.info("Token已刷新，用户: {}", username);
            }
            
            return true;
            
        } catch (Exception e) {
            logger.error("Token刷新检查异常: {}", e.getMessage(), e);
            return true; // 异常时继续执行，交给下一个拦截器处理
        }
    }
    
    /**
     * 检查是否是排除路径
     */
    private boolean isExcludePath(String requestURI) {
        return EXCLUDE_PATHS.stream().anyMatch(requestURI::startsWith);
    }
    
    /**
     * 从请求中获取Token
     */
    private String getTokenFromRequest(HttpServletRequest request) {
        return request.getHeader("access-key");
    }
}